import 'package:flutter/material.dart';

///内容构建器
typedef Widget AppBottomSheetBuilder(
    BuildContext context, ScrollPhysics physics);

///应用底部弹框
class AppBottomSheet extends StatefulWidget {
  const AppBottomSheet({
    Key key,
    this.height = 500,
    this.builder,
    this.bgDecoration,
  }) : super(key: key);

  ///底部栏高度
  final double height;

  ///子控件
  final AppBottomSheetBuilder builder;

  ///背景样式
  final Decoration bgDecoration;

  @override
  _AppBottomSheetState createState() => _AppBottomSheetState();
}

class _AppBottomSheetState extends State<AppBottomSheet> {
  ///是否可以滚动
  bool _shouldDrag;

  ///是否向上拖动
  bool _isDragUp;

  @override
  void setState(fn) {
    if (this.mounted) super.setState(fn);
  }

  @override
  void initState() {
    super.initState();
    _shouldDrag = true;
    _isDragUp = true;
  }

  @override
  void dispose() {
    super.dispose();
  }

  ///原始指针监听
  void _onPointerMove(PointerMoveEvent p) {
    if (p.localDelta.dy > 0 && _isDragUp) {
      _isDragUp = false;
    } else if (p.localDelta.dy < 0 && !_isDragUp) {
      _isDragUp = true;
      if (!_shouldDrag)
        setState(() {
          _shouldDrag = true;
        });
    }
  }

  ///列表滚动监听
  bool _onNotification(ScrollNotification n) {
    if (n.metrics.atEdge && n.metrics.pixels <= n.metrics.minScrollExtent) {
      if (_shouldDrag && !_isDragUp) {
        setState(() {
          _shouldDrag = false;
        });
      }
    } else if (!_shouldDrag) {
      setState(() {
        _shouldDrag = false;
      });
    }

    return true;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: widget.height,
      decoration: widget.bgDecoration ?? BoxDecoration(color: Colors.white),
      child: Listener(
        onPointerMove: _onPointerMove,
        child: NotificationListener(
          onNotification: _onNotification,
          child: widget.builder(context,
              _shouldDrag ? null : const NeverScrollableScrollPhysics()),
        ),
      ),
    );
  }
}
